# 字典是另一种可变容器模型，且可存储任意类型对象。
# 字典的每个键值 key=>value 对用冒号 : 分割，每个键值对之间用逗号 , 分割，整个字典包括在花括号 {} 中 ,格式如下所示：
# d = {key1 : value1, key2 : value2 }

# 键一般是唯一的，如果重复最后的一个键值对会替换前面的，值不需要唯一。

dict1 = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
dict2 = {'abc': 456}
dict3 = {'abc': 123, 98.6: 37}

# 访问字典里的值
item = dict1['Beth']
print(f"{dict1} 中key是‘Beth’的value是：", item)

try:
    item = dict1['Bet']
    print(f"{dict1}，访问字典中没有的key‘Bet’，结果是：", item)
except KeyError:
    print("KeyError: key not exists")
finally:
    print(f"{dict1}，访问字典中没有的key‘Bet’，会有异常")

# 新增/修改字典
# 向字典添加新内容的方法是增加新的键/值对，修改已有键/值对
dict3['abc'] = 'abc'
print(f"{dict3} 的key是‘abc’的value改成‘abc’")
dict3['a'] = 'a'
print(f"{dict3} 添加新的key是‘a’和value改成‘a’")

# 删除元素
del dict3['a']
print(f"{dict3} 的key是‘a’的元素已经删除")

# 清空字典
dict3.clear()
print(f"{dict3} 清空字典")
# 将清空的字典复原，方便后面使用
dict3 = {'abc': 123, 98.6: 37}

# 删除字典
dict = {1: 1, 2: 2}
del dict
print(f"{dict} 删除字典dict")

# 字典键的特性
# 字典值可以没有限制地取任何python对象，既可以是标准的对象，也可以是用户定义的，但键不行。
# 不允许同一个键出现两次。创建时如果同一个键被赋值两次，后一个值会被记住
# 键必须不可变，所以可以用数字，字符串或元组充当，所以用列表就不行

# 字典内置函数&方法
# 序号	函数及描述
# 1	cmp(dict1, dict2)
# 比较两个字典元素。
# 2	len(dict)
# 计算字典元素个数，即键的总数。
# 3	str(dict)
# 输出字典可打印的字符串表示。
item = str(dict1)
print(f"将字典类型转成字符类型", type(dict1), " => ", type(item))

# 4	type(variable)
# 返回输入的变量类型，如果变量是字典就返回字典类型。
item = type(dict1)
print(f"可以查看当前数据类型是：", item)


# Python字典包含了以下内置方法：
#
# 序号	函数及描述
# 1	dict.clear()
# 删除字典内所有元素
# 2	dict.copy()
# 返回一个字典的浅复制
dict4 = {'user': 'runoob', 'num': [1, 2, 3]}
dict5 = dict4  # 浅拷贝: 引用对象
dict6 = dict4.copy()  # 浅拷贝：深拷贝父对象（一级目录），子对象（二级目录）不拷贝，还是引用
# 修改 data 数据
dict4['user'] = 'root'
dict4['num'].remove(1)
# 输出结果
print(dict4)
print(dict5)
print(dict6)
print("实例中 dict5 其实是 dict4 的引用（别名），所以输出结果都是一致的，dict6 父对象进行了深拷贝，不会随dict4 修改而修改，子对象是浅拷贝所以随 dict4 的修改而修改。")

# 3	dict.fromkeys(seq[, val])
# 创建一个新字典，以序列 seq 中元素做字典的键，val 为字典所有键对应的初始值
dict = dict1.fromkeys([1, 2, 3, 4], "s")
print(f"创建一个新字典，key是[1, 2, 3, 4], value统一是“s”，结果是：", dict)

# 4	dict.get(key, default=None)
# 返回指定键的值，如果值不在字典中返回default值
item = dict3.get('abc')
print(f"获取{dict3}中key是‘abc’的值：", item)

# 5	dict.has_key(key)
# 如果键在字典dict里返回true，否则返回false
# Python 3.X 里不包含 has_key() 函数，被 __contains__(key) 替代:
item = dict3.__contains__('abc')
print(f"获取{dict3}中是否包含‘abc’的key：", item)

# 6	dict.items()
# 以列表返回可遍历的(键, 值) 元组数组
item = dict3.items()
print(f"返回一个列表，列表里面是键值的元组：", item)

# 7	dict.keys()
# 以列表返回一个字典所有的键
item = dict3.keys()
print(f"返回一个key的列表：", item)

# 8	dict.setdefault(key, default=None)
# 和get()类似, 但如果键不存在于字典中，将会添加键并将值设为default
dict = {'a': 1, 2: 'b'}
dict.setdefault("c")
print(f"{dict} 设置一个默认的key-value， 如果之不存在， 默认为default，目前设置key是‘c’")

# 9	dict.update(dict2)
# 把字典dict2的键/值对更新到dict里
dicta = {'a': 1, 2: 'b', '4': '8'}
dictb = {'a': 7, 2: 'z', 5: 0}
dicta.update(dictb)
print(f"把字典dictb的键/值对更新到dicta里：", dicta)

# 10	dict.values()
# 以列表返回字典中的所有值
item = dict3.values()
print(f"返回一个字典的values列表：", item)

# 11	pop(key[,default])
# 删除字典给定键 key 所对应的值，返回值为被删除的值。key值必须给出。 否则，返回default值。
dicta = {'a': 1, 2: 'b', '4': '8'}
dicta.pop('a')
print(f"删除key为‘a’的数据。", dicta)

# 12	popitem()
# 返回并删除字典中的最后一对键和值。
dicta = {'a': 1, 2: 'b', '4': '8'}
dicta.popitem()
print(f"删除最后一个键值对", dicta)
